/*
 * Copyright � 2008 Nokia Corporation.
 */


#include <fbs.h>
#include <eikenv.h>
#include <sudoku_svg.mbg>

#include "SudokuStatisticControl.h"
#include "SudokuGridControl.h"
#include "SudokuGameLogic.h"
#include "SudokuAppView.h"
#include "GraphicEngine.h"
#include "SudokuAppUi.h"



// ----------------------------------------------------------------------------
// CGameTimer
// ----------------------------------------------------------------------------
CGameTimer* CGameTimer::NewL()
    {
    CGameTimer* self = new (ELeave)CGameTimer(CActive::EPriorityIdle);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

void CGameTimer::ConstructL()
    {
    CTimer::ConstructL();
    CTimer::After(TTimeIntervalMicroSeconds32(1000000));
    }

CGameTimer::~CGameTimer()
    {
    Cancel();
    }

CGameTimer::CGameTimer(TInt aPriority)
: CTimer(aPriority)
    {
    CActiveScheduler::Add(this);
    }

void CGameTimer::DoCancel()
    {
    }

void CGameTimer::Reset()
    {
    Cancel();
    iSeconds = 0;
    CTimer::After(TTimeIntervalMicroSeconds32(1000000));
    }

void CGameTimer::Continue()
    {
    Cancel();
    CTimer::After(TTimeIntervalMicroSeconds32(1000000));
    }

void CGameTimer::RunL()
    {
    if (iStatus.Int()==KErrNone)
        {
        iSeconds++;
        CTimer::After(TTimeIntervalMicroSeconds32(1000000));
        }
    }

TInt CGameTimer::RunError(TInt /*aError*/)
    {
    iSeconds = 0;
    return KErrNone;
    }









// ----------------------------------------------------------------------------
// CSudokuStatisticControl
// ----------------------------------------------------------------------------
CSudokuStatisticControl::CSudokuStatisticControl (CSudokuContainerControl& aParent, 
        CFbsBitGc*& aBgc) : iParent(aParent), iBgc(aBgc)
    {
    // No implementation required
    }

CSudokuStatisticControl::~CSudokuStatisticControl ( )
    {
    delete iGameTimer;
    }

CSudokuStatisticControl* CSudokuStatisticControl::NewLC (CSudokuContainerControl& aParent, 
        const TRect& aRect, CFbsBitGc*& aBgc)
    {
    CSudokuStatisticControl* self = new (ELeave)CSudokuStatisticControl(aParent, aBgc);
    CleanupStack::PushL (self );
    self->ConstructL (aRect);
    return self;
    }

CSudokuStatisticControl* CSudokuStatisticControl::NewL (CSudokuContainerControl& aParent, 
        const TRect& aRect, CFbsBitGc*& aBgc)
    {
    CSudokuStatisticControl* self=CSudokuStatisticControl::NewLC (aParent, aRect, aBgc);
    CleanupStack::Pop ( ); // self;
    return self;
    }

void CSudokuStatisticControl::ConstructL (const TRect& /*aRect*/)
    {
    SetContainerWindowL(iParent);
    
    iGameTimer = CGameTimer::NewL();

    iGraphicEngine = static_cast<CSudokuAppUi*>(iEikonEnv->EikAppUi())->GraphicEngine();
    }

void CSudokuStatisticControl::Draw( const TRect& /*aRect*/ ) const
    {
    // Remember to draw into backbuffer iBgc
    iBgc->SetPenColor(KRgbBlack);

    DrawStatisticData();
    }

void CSudokuStatisticControl::ResetGameTimer()
    {
    iGameTimer->Reset();
    }

void CSudokuStatisticControl::ContinueGameTimer()
    {
    iGameTimer->Continue();
    }

void CSudokuStatisticControl::StopGameTimer()
    {
    iGameTimer->Cancel();
    }

void CSudokuStatisticControl::DrawStatisticData() const
    {
    // Use this smaller font
    if (iUseFont)
        {
        iParent.UseFont(iUseFont);
        }
    
    TRect rect = Rect();

    // Draw background
    TRect itemRect = TRect(TPoint(0,0),rect.Size());
    iBgc->BitBltMasked(Rect().iTl,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgStatistic),
                       itemRect,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgStatistic_mask),
                       EFalse);

    // Draw others
    
    // Moves
    itemRect = TRect(TPoint(0,0),iGraphicEngine->BitmapSVG(EMbmSudoku_svgMove)->SizeInPixels());
    iBgc->BitBltMasked(iHeadersTl,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgMove),
                       itemRect,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgMove_mask),
                       EFalse);

    iBgc->DrawText(iMoves,iValuesTl);
    
    // Empty
    itemRect = TRect(TPoint(0,0),iGraphicEngine->BitmapSVG(EMbmSudoku_svgEmpty)->SizeInPixels());
    iBgc->BitBltMasked(iHeaders2Tl,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgEmpty),
                       itemRect,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgEmpty_mask),
                       EFalse);
    iBgc->DrawText(iEmpty,iValues2Tl);

    // Time
    itemRect = TRect(TPoint(0,0),iGraphicEngine->BitmapSVG(EMbmSudoku_svgTime)->SizeInPixels());
    iBgc->BitBltMasked(iHeaders3Tl,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgTime),
                       itemRect,
                       iGraphicEngine->BitmapSVG(EMbmSudoku_svgTime_mask),
                       EFalse);
    iBgc->DrawText(iTime,iValues3Tl);
    }

void CSudokuStatisticControl::UpdateData()
    {
    iTime.Zero();
    iMoves.Zero();
    iEmpty.Zero();

    TInt total = iGameTimer->Seconds();
    TInt minutes = total / 60;
    TInt seconds = total % 60;
    
    if (minutes<10)
        {
        iTime.AppendNum(0);
        iTime.AppendNum(minutes);
        }
    else
        {
        iTime.AppendNum(minutes);
        }
    
    iTime.Append(_L(":"));

    if (seconds<10)
        {
        iTime.AppendNum(0);
        iTime.AppendNum(seconds);
        }
    else
        {
        iTime.AppendNum(seconds);
        }
    
    iMoves.AppendNum(iParent.GameLogic()->MovesCount());
    iEmpty.AppendNum(iParent.GameLogic()->EmptyCount());
    
    // Game Over!
    if (iParent.GameLogic()->EmptyCount()==0 && iGameTimer->IsActive())
        {
        StopGameTimer();
        TRAPD(err,static_cast<CSudokuAppUi*>(iEikonEnv->EikAppUi())->ShowGameOverL());
        }
    }


void CSudokuStatisticControl::SizeChanged()
    {
    TRect rect = Rect();
    iUseFont = iParent.StatisticFont();

    // Update graphic size
    iGraphicEngine->SetSVGBitmapSize(EMbmSudoku_svgStatistic,Rect().Size());
    TSize picSize = TSize(iUseFont->HeightInPixels()-3,iUseFont->HeightInPixels()-3);
    iGraphicEngine->SetSVGBitmapSize(EMbmSudoku_svgEmpty,picSize);
    iGraphicEngine->SetSVGBitmapSize(EMbmSudoku_svgMove,picSize);
    iGraphicEngine->SetSVGBitmapSize(EMbmSudoku_svgTime,picSize);
    
    // Do we have room for statistics data texts (free height)?
    TInt room = rect.Height() - iUseFont->HeightInPixels() * 4;
    if (room<=0)
        {
        // Put statistic into same row
        TInt height = ((rect.Height() - iUseFont->HeightInPixels()) / 2) + iUseFont->HeightInPixels();
        TInt cell = rect.Width() / 15;
        
        iHeadersTl = rect.iTl;
        iHeadersTl.iX += cell*1;
        iHeadersTl.iY += height;
        iValuesTl = iHeadersTl;
        iValuesTl.iX += cell*1.7;
        iHeadersTl.iY -= picSize.iHeight;
        
        iHeaders2Tl = rect.iTl;
        iHeaders2Tl.iX += cell*4.5;
        iHeaders2Tl.iY += height;
        iValues2Tl = iHeaders2Tl;
        iValues2Tl.iX += cell*1.7;
        iHeaders2Tl.iY -= picSize.iHeight;

        iHeaders3Tl = rect.iTl;
        iHeaders3Tl.iX += cell*8.7;
        iHeaders3Tl.iY += height;
        iValues3Tl = iHeaders3Tl;
        iValues3Tl.iX += cell*1.9;
        iHeaders3Tl.iY -= picSize.iHeight;
        }
    else
        {
        // Room for different rows

        // Row cap between headers/values
        TInt cap = (rect.Height() - iUseFont->HeightInPixels() * 3) / 4;

        // Is there enought width?
        TInt textWidth = iUseFont->TextWidthInPixels(_L("T-00:00"));
        if (textWidth>rect.Width()-10)
            {
            iUseFont = iParent.StatisticMinorFont();
            textWidth = iUseFont->TextWidthInPixels(_L("T-00:00"));
            }
            
        iHeadersTl.iY = rect.iTl.iY + cap;
        iHeadersTl.iY += iGraphicEngine->BitmapSVG(EMbmSudoku_svgMove)->SizeInPixels().iHeight;

        iHeadersTl.iX = rect.iTl.iX + (rect.Width() - textWidth) / 2;
        iValuesTl.iX = iHeadersTl.iX + iGraphicEngine->BitmapSVG(EMbmSudoku_svgMove)->SizeInPixels().iWidth*1.5;
        iValuesTl.iY = iHeadersTl.iY;

        // Rest headers and values
        iHeaders2Tl = TPoint(iHeadersTl.iX, iHeadersTl.iY + cap + iUseFont->HeightInPixels());
        iHeaders3Tl = TPoint(iHeaders2Tl.iX, iHeaders2Tl.iY + cap + iUseFont->HeightInPixels());
        iValues2Tl = TPoint(iValuesTl.iX, iValuesTl.iY + cap + iUseFont->HeightInPixels());
        iValues3Tl = TPoint(iValues2Tl.iX, iValues2Tl.iY + cap + iUseFont->HeightInPixels());

        
        iHeadersTl.iY -= picSize.iHeight;
        iHeaders2Tl.iY -= picSize.iHeight;
        iHeaders3Tl.iY -= picSize.iHeight;
        }

    
    UpdateData();    
    }







